/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "se_hianalytics.h"

#include "loghelper.h"
#include "common_utils.h"
#include "cJSON.h"
#include "file_ex.h"

namespace OHOS {
namespace SE {

SeHiAnalytics::SeHiAnalytics()
{
}

SeHiAnalytics& SeHiAnalytics::GetInstance()
{
    static SeHiAnalytics instance;
    return instance;
}

void SeHiAnalytics::SeEventLog(int logId, const std::string &arg)
{
    uint32_t logLen = AppendSeEventLog(logId, arg);
    if (logLen >= EVENT_LOG_MAX_SIZE) {
        WriteLogToFile();
    }
}

void SeHiAnalytics::SeEventLog(int logId, const std::string &arg1, const std::string &arg2)
{
    uint32_t logLen = AppendSeEventLog(logId, arg1, arg2);
    if (logLen >= EVENT_LOG_MAX_SIZE) {
        WriteLogToFile();
    }
}

uint32_t SeHiAnalytics::AppendSeEventLog(int logId, const std::string &arg)
{
    std::unique_lock<std::shared_mutex> guard(mutex_);
    std::string newLog = CommonUtils::GetLocalTimeStampWithDate() + COMMA_PARSER +  std::to_string(logId) +
        COMMA_PARSER + CommonUtils::GetUniqueTag() + COMMA_PARSER + arg + VERTICAL_BAR_PARSER;
    seEventLog_.append(newLog);
    return seEventLog_.length();
}

uint32_t SeHiAnalytics::AppendSeEventLog(int logId, const std::string &arg1, const std::string &arg2)
{
    std::unique_lock<std::shared_mutex> guard(mutex_);
    std::string newLog = CommonUtils::GetLocalTimeStampWithDate() + COMMA_PARSER +  std::to_string(logId) +
        COMMA_PARSER + CommonUtils::GetUniqueTag() + COMMA_PARSER + arg1 + COMMA_PARSER + arg2 + VERTICAL_BAR_PARSER;
    seEventLog_.append(newLog);
    return seEventLog_.length();
}

void SeHiAnalytics::CheckAndRmvLogFile()
{
    if (!FileExists(SE_EVENT_FILE_PATH)) {
        InfoLog("%{public}s not exist yet", SE_EVENT_FILE_PATH);
        return;
    }

    uint32_t fileSize = CommonUtils::GetFileSize(SE_EVENT_FILE_PATH);
    InfoLog("fileSize = %{public}d", fileSize);
    if (fileSize > FILE_MAX_SIZE) {
        // delete SE_EVENT_FILE_PATH
        if (std::remove(SE_EVENT_FILE_PATH) != 0) {
            ErrorLog("remove file:%{public}s failed", SE_EVENT_FILE_PATH);
        }
    }
}

void SeHiAnalytics::WriteLogToFile()
{
    std::unique_lock<std::shared_mutex> guard(mutex_);
    if (seEventLog_.empty()) {
        ErrorLog("nothing to write");
        return;
    }
    CheckAndRmvLogFile();
    cJSON *writeStrJson = cJSON_CreateObject();
    if (writeStrJson == nullptr) {
        cJSON_Delete(writeStrJson);
        ErrorLog("cJSON_CreateObject error");
        return;
    }
    if (!seEventLog_.empty() &&
        cJSON_AddStringToObject(writeStrJson, EVENT_TYPE_SE, seEventLog_.c_str()) == nullptr) {
        cJSON_Delete(writeStrJson);
        ErrorLog("cJSON_AddStringToObject error");
        return;
    }
    char *writeStr = cJSON_Print(writeStrJson);
    if (writeStr == nullptr) {
        cJSON_Delete(writeStrJson);
        ErrorLog("cJSON_Print writeStr error");
        return;
    }
    if (!SaveStringToFile(SE_EVENT_FILE_PATH, writeStr, false)) {
        ErrorLog("write file:%{public}s failed!", SE_EVENT_FILE_PATH);
        cJSON_free(writeStr);
        cJSON_Delete(writeStrJson);
        return;
    }
    InfoLog("writeStr len = %{public}lu", seEventLog_.length());
    seEventLog_ = "";
    cJSON_free(writeStr);
    cJSON_Delete(writeStrJson);
}

void SeHiAnalytics::WriteLogWithoutCondition()
{
    WriteLogToFile();
}
}
}